package com.bit.cfdi.web.vm.negocio;

import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.zkoss.bind.annotation.AfterCompose;
import org.zkoss.bind.annotation.BindingParam;
import org.zkoss.bind.annotation.Command;
import org.zkoss.bind.annotation.ContextParam;
import org.zkoss.bind.annotation.ContextType;
import org.zkoss.bind.annotation.DependsOn;
import org.zkoss.bind.annotation.GlobalCommand;
import org.zkoss.bind.annotation.Init;
import org.zkoss.bind.annotation.NotifyChange;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.select.Selectors;
import org.zkoss.zk.ui.select.annotation.VariableResolver;
import org.zkoss.zk.ui.select.annotation.Wire;
import org.zkoss.zk.ui.select.annotation.WireVariable;
import org.zkoss.zul.Label;
import org.zkoss.zul.Messagebox;
import org.zkoss.zul.Messagebox.ClickEvent;

import com.bit.cfdi.web.constants.CFDIConstants;
import com.bit.cfdi.web.constants.NavInfrastructure;
import com.bit.cfdi.web.domain.Negocio;
import com.bit.cfdi.web.domain.Usuario;
import com.bit.cfdi.web.domain.UsuarioNegocio;
import com.bit.cfdi.web.services.UsuarioNegocioService;
import com.bit.cfdi.web.session.SessionUtils;

@VariableResolver(org.zkoss.zkplus.spring.DelegatingVariableResolver.class)
public class NavNegocioViewModel {
	
	private Logger log = LogManager.getLogger(this.getClass().getName());
	
	@WireVariable private SessionUtils sessionUtils;
	@WireVariable private UsuarioNegocioService usuarioNegocioService;
	
	//UI wired components
	@Wire private Label editLabel;
	
	//To show in form
	private NegocioViewParser currentBusiness;
	private List<NegocioViewParser> otherUserBusiness;
	private Integer numberOfBusinessRows;
	
	@Init
	public void init() {
		otherUserBusiness = new ArrayList<NegocioViewParser>();
	}
	
	@AfterCompose
	public void afterCompose(@ContextParam(ContextType.VIEW) Component view) {
		attachComponents(view);
		retrieveInfo();
	}
	
	//Geters-Setters
	public NegocioViewParser getCurrentBusiness() {
		return currentBusiness;
	}
	
	public List<NegocioViewParser> getOtherUserBusiness() {
		return otherUserBusiness;
	}
	
	@DependsOn({"otherUserBusiness"})
	public Integer getNumberOfBusinessRows() {
		return numberOfBusinessRows;
	}
	
	//Local Commands
	@Command
	public void changeBusiness(@BindingParam("negIndex") Integer negIndex) {
		log.info("business change to index: "+negIndex);
		if(negIndex<0 || otherUserBusiness.size()-1<negIndex) {
			log.info("Index out of bounds");
			return;
		}
		Messagebox.show("Deseas cambiar de negocio al negocio: " +
				otherUserBusiness.get(negIndex).getNombre(), 
				new Messagebox.Button[]{Messagebox.Button.YES, 
										Messagebox.Button.CANCEL}, 
				new ChangeBusinessMessageEventListener(negIndex));
	}
	
	private class ChangeBusinessMessageEventListener 
			implements EventListener<ClickEvent> {
		
		Integer selectedIndex;
		
		ChangeBusinessMessageEventListener(Integer selectedIndexPassed) {
			selectedIndex = selectedIndexPassed;
		}
		
		@Override
		public void onEvent(ClickEvent event) throws Exception {
			switch(event.getButton()) {
				case YES: {
					performBusinessChange(selectedIndex);
				}break;
				default:{
				}break;
			}
		}
	}
	
	//Global Commands
	@GlobalCommand @NotifyChange({"*"})
	public void negocioRefreshNegocioInfo() {
		log.info("negocioRefreshNegocioInfo() called");
		retrieveBusinessInSessionInfo();
	}
	
	@GlobalCommand @NotifyChange({"*"})
	public void negocioRefreshOtherUserBusiness() {
		retrieveOtherUserBusiness();
	}
	
	//private methods
	private void attachComponents(Component view) {
		Selectors.wireComponents(view, this, false);
	}
	
	public void retrieveInfo() {
		retrieveBusinessInSessionInfo();
		retrieveOtherUserBusiness();
	}
	
	private void retrieveBusinessInSessionInfo() {
		Negocio negocio = (Negocio) sessionUtils.getFromSession(
				SessionUtils.NEGOCIO);
		Usuario usuario = (Usuario) sessionUtils.getFromSession(
				SessionUtils.USUARIO);
		currentBusiness = new NegocioViewParser(negocio, usuario, 
				usuarioNegocioService);
		showEditButton(currentBusiness.getPermisos());
	}
	
	private void showEditButton(final List<String> permisos) {
		if(!permisos.contains(NavInfrastructure.KEY_KING_NEGOCIO)) {
			editLabel.detach();
			return;
		}
	}
	
	private void retrieveOtherUserBusiness() {
		Negocio negocio = (Negocio) sessionUtils.getFromSession(
				SessionUtils.NEGOCIO);
		Usuario usuario = (Usuario) sessionUtils.getFromSession(
				SessionUtils.USUARIO);
		
		otherUserBusiness.clear();
		List<UsuarioNegocio> retrievedBusiness = usuarioNegocioService
				.getNegociosFromUsuario(usuario);
		for(UsuarioNegocio current : retrievedBusiness) {
			if(!current.getNegocio().getIdNegocio().equals(
					negocio.getIdNegocio())) {
				otherUserBusiness.add(new NegocioViewParser(
						current.getNegocio(), usuario, usuarioNegocioService));
			}
		}
		numberOfBusinessRows = 4;
		if(otherUserBusiness.size()<4) {
			numberOfBusinessRows = otherUserBusiness.size();
		}
	}
	
	private void performBusinessChange(final Integer index) {
		NegocioViewParser toChange = otherUserBusiness.get(index);
		sessionUtils.addToSession(SessionUtils.NEGOCIO, toChange.getNegocio());
		Executions.getCurrent().sendRedirect(CFDIConstants.CFDIPages.HOME_URL);
	}
	
}
